 /*
  *@(#)ImgLink.java		 2000
  *
  * Copyright: MetaPlus Inc & Inquiry Management Systems Ltd.  2000
  *
  * This software is the proprietary information of MetaPlus Inc & 
  * Inquiry Management Systems Ltd.  
  * Use is subject to license terms.
  */
package com.ims.iaa.AD;

import com.ims.iaa.IaaDebug; 
import com.ims.iaa.IaaUtil; 
import com.ims.iaa.URLUtil;

import java.io.*; 
import java.net.*; 
import java.sql.*;
import java.util.List;

/**
  * This class represents image link data collected by spiders. 
  * In 2.0 version, this class extends from AdDataLink, some method
  * has been move to AdDataLink, and many variable has become private,
  * so some related class has been modify, such as 
  * ImpAnalyzer, PageAnalyzer, SpiderDataStream.
  *
  * @author Michael Liao 
  * @author Anthony Zhang
  *
  * @version 1.00, 25 Sept. 2000
  * 
  * @author ShengMeng Bai
  * @version 2.00, 29 JUL. 2004
  *
  */
  public class ImgLink extends AdDataLink  {
	private AdImage m_objImage = new AdImage();

	private String m_sUserAgent;
	
	private String  m_sAdvertiser = "";
	private String  m_sImageSite = "";
	
	private Timestamp m_objCollectTime;

	//private 
	public transient SimpleCookies m_objCookie;

	private URL m_objSrcUrl;// the <IMG src=> content;
	private int m_iSrcReqStatus ;

	private URL m_objTargetUrl;// the <A href=> ;

	private int m_iTargetReqStatus;

	private URL m_objRealTargetUrl;// the real target url after connect to the target

	private URL m_objContainerUrl;		// the url in which this image link was contained
	//save the image height and width, if can't get real height and width from AdImage, save it.
	private int m_iHeight = 0;
	private int m_iWidth = 0;
	
	/**
	 * The constructor construct new Image Link, 
	 * 
	 * @param urlSRC, image URL
	 * @param target, Image tagret URL
	 * @param container, The web page ehich contain image.
	 * @throws MalformedURLException
	 */
	public ImgLink(URL urlSRC, URL container, String target) throws MalformedURLException {
	    this.setOriginalImgURL(urlSRC.toExternalForm());
		m_objSrcUrl = urlSRC;
		m_objTargetUrl = URLUtil.getURL(container, target);
		m_objContainerUrl = container;
	}
	/**
	 * The constructor construct updated Image impression, 
	 * @param urlSRC, image URL
	 * @param iImpID, the impression ID which saved in database
	 * @param iImageID, the image ID which saved in database
	 * @param sUserAgent
	 * 
	 * @see com.ims.iaa.SpiderDBConnectionImpl#getReConnectImp(int)
	 */
	public ImgLink(URL urlSRC, int iImpID, int iImageID, String sUserAgent){
		m_objSrcUrl = urlSRC;
		setOldImpressionID(iImpID);
		setOldImageID(iImageID);
		setUserAgent(sUserAgent);
	}
	/**
	 * Get the advertisement type, it is "IMG" or "IMG/POPUP". 
	 * @return
	 */
	public String getAdType()  {
		if(isPopupData()){
			return ADTYPE_POPUP_IMAGE;
		}else{
			return ADTYPE_IMAGE;
		}
	}
	public AdData getAdData(){
		return m_objImage;
	}
	public int getHeight(){
		return m_objImage.getHeight();
	}
	public void setHeight(int iHeight){
	    m_iHeight = iHeight;
	}
	public int getWidth(){
		return m_objImage.getWidth();
	}
	public void setWidth(int iWidth){
	    m_iWidth = iWidth;
	}
	public void setUserAgent(String agent)  {
		m_sUserAgent = agent;
	}
	
	public URL getSrcURL(){
		return m_objSrcUrl;
	}
	
	public String getSrcURLStr(){
		return m_objSrcUrl.toString();
	}
	public URL getTargetURL() {
		return m_objTargetUrl;
	}
	public String getTargetURLStr(){
		return m_objTargetUrl.toString();
	}
	
	
	public Timestamp getCollectTime() {
		// collectTime was set in the connectToRecources()  method;
		return m_objCollectTime;
	}
	public void setCollectTime(Timestamp objCollectTime)
	{
	    this.m_objCollectTime = objCollectTime ;
	}//changsheng ++
	public String getAdvertiser()  {
		// advertiser was set in the connectToRecources()  method;
		return m_sAdvertiser;
	}
	public String getAdTarget() {
		return m_objRealTargetUrl.toString();
	}
	public String getAdDataSite()  {
		// imageSite was set in the connectToRecources()  method;
		return m_sImageSite;
	}
	public void setAdDataSite(String sImageSite)
	{
	    this.m_sImageSite = sImageSite ;
	}//changsheng ++

	public URL getContainerURL() {
		return m_objContainerUrl;
	}

	public URL getRealTargetURL() throws MalformedURLException {
		return m_objRealTargetUrl;
	}

	public String getRealTargetURLStr(){
		if(m_objRealTargetUrl == null){
			return null;
		}
		return m_objRealTargetUrl.toString();
	}
	public int getSrcReqStatus(){
		return m_iSrcReqStatus;
	}
	public void setSrcReqStatus(int srcReqStatus)
	{
	    this.m_iSrcReqStatus = srcReqStatus ;
	}//changsheng ++
	public int getTargetReqStatus(){
		return m_iTargetReqStatus;
	}

	
	private void connectToResource() {
		// try to get the image source content.
		URLConnection uc = null;
		m_objCookie = new SimpleCookies();

		try  {
		    HrefParser href = new HrefParser(m_objSrcUrl, m_sUserAgent);
		    if(!href.connect()){
		        //even it is fail, we still need get the mime type.
				m_objImage.setDataType(href.getMimeType());
				m_iSrcReqStatus = CONN_FAILURE;
		        return;
		    }
		    //get the redirect URL
		    m_objSrcUrl=href.getRedirectURL();
			
		    uc = href.getConnection();
			//read cookie after connect()
			m_objCookie.readCookies( uc );
			m_objImage.setDataType(href.getMimeType());
			m_objImage.setDataSize(href.getContentLength());
			if(href.getContentLength()==AdImage.MAXIMAGESIZE-1)
			{
				IaaUtil.log("-------------------------");

				//IaaUtil.log("the srcURL of the image:"+ getSrcURLStr());
				//IaaUtil.log("the targetURL of the image:"+ getTargetURLStr());
				//IaaUtil.log("the realTargetURL of the image:"+ getRealTargetURLStr());
				//IaaUtil.log("the containerURL of the image:"+ getContainerURL().getHost());
			}
			m_sImageSite = uc.getURL().getHost();
			m_iSrcReqStatus = CONN_SUCCESS;
		} catch(Exception e)  {
			if(IaaDebug.Debug) 			
				IaaUtil.log("!!!!Error make connection to the image " + e);		
		}

		m_objCollectTime = new Timestamp(  System.currentTimeMillis() );
		if (AdImage.SAVEIMAGE && (m_objImage.getDataSize() < AdImage.MAXIMAGESIZE))  {
			if(IaaDebug.AuxDebug)IaaDebug.begin("connect to the image ");		
			try  {
				IaaDebug.begin("getInputStream for image" + uc.getURL());
				BufferedInputStream bs = new BufferedInputStream(uc.getInputStream());
				IaaDebug.end("getInputStream " + uc.getURL());
	
				byte[] buf = new byte[5120];
				int readNum =0;

				ByteArrayOutputStream picOutStream = new ByteArrayOutputStream();

				IaaDebug.begin("read image inputStream " + uc.getURL());
				while ( (readNum = bs.read(buf)) != -1)  {
						picOutStream.write(buf,0,readNum);
				}
				
				bs.close();
				IaaDebug.end("read image inputStream " + uc.getURL());

				if(m_objImage.getDataSize() == AdImage.MAXIMAGESIZE-1)
				{
					IaaUtil.log("connectToResource-->the size of the image now is  " + m_objImage.getDataSize() );
					m_objImage.setDataSize(picOutStream.toByteArray().length);//added by yxy 2008-7-4
					IaaUtil.log("connectToResource-->the size of the image after updated is "+m_objImage.getDataSize());
					IaaUtil.log(picOutStream.toByteArray().toString()+"\n\n\n\n");
				}
				m_objImage.setData(picOutStream.toByteArray());
				IaaDebug.end("set image data");
				
				
				// picOutStream.size() should equals to the length of imageData array
				// imageSize = picOutStream.size();
				picOutStream.close();
				if(IaaDebug.AuxDebug)IaaDebug.end("connect to the image ");
			} catch ( Exception e ) {
				m_iSrcReqStatus = CONN_FAILURE;
				IaaUtil.log( "Get image from the connection input stream error " + e );
			}
		} else {
			if(IaaDebug.Debug) IaaUtil.log("Image data too big to be saved.");	
			//Note: either image is too big or we do not want to save the image, 
			// then the imageData is still null
			// imageSize = imageData.length;
		}
		// connect to the anchor target. to get the redirect url.
		// if is reconenct, don't do it.
		if(getOldImpressionID() < 0){
		    HrefParser href = new HrefParser(m_objTargetUrl, m_sUserAgent);
		    if(href.connect()){
		        //++changsheng 2006-6-30 move out if(href.connect())
/*				m_objRealTargetUrl = href.getRedirectURL();
				m_sAdvertiser = m_objRealTargetUrl.getHost();*/
				m_iTargetReqStatus = CONN_SUCCESS;
		    }else{
		        m_iTargetReqStatus = CONN_FAILURE;
		    }				
		    m_objRealTargetUrl = href.getRedirectURL();
			m_sAdvertiser = m_objRealTargetUrl.getHost();
		}
		
		IaaDebug.end("target process");
		//we try to get image height and width here, so we can store them into the database without delay.
		//Since there is an interval (connect to the real target) between here and we get the image, 
		//usually there should be no wait occured
		m_objImage.prepareImageHeight();
		IaaDebug.end("get image height");
		m_objImage.prepareImageWidth();
		IaaDebug.end("get image width");
		//after save the image data and get the widht and height,
		//if can't get the width and height, set it to web page setting
		if(m_objImage.getWidth() == AdData.NOTEXIST || m_objImage.getHeight() == AdData.NOTEXIST){
		    m_objImage.setHeight(m_iHeight);
		    m_objImage.setWidth(m_iWidth);
		}
	}
	/* (non-Javadoc)
	 * @see com.ims.iaa.AD.AdDataLink#parse(List lstAgency)
	 * 
	 * updated by yxy 2008-05-14
	 */
	public boolean parse(List lstAgency, List lstAdSize) {
		IaaDebug.begin("parse ImagLink");	
		// try to figure out if this image is a ad
		int iImgWidth = getWidth();
		int iImgHeight = getHeight();
		if( ImageConnectedFlag == false ){
			// 1. base on the image width and height
			if ( iImgWidth < IaaDebug.m_iMinImageWidth &&
				 iImgHeight < IaaDebug.m_iMinImageHeight && 
				iImgWidth != AdData.UNKNOWN &&
				iImgHeight != AdData.UNKNOWN ) {
				
				addReason( "the image is too small; ") ;
				return false;
				
			} else {
				connectToResource();
			}
			
			// 2. parse the target hostname
			if ( isAdAgency(lstAgency) ) {
				incPossibility(100);
				addReason( "point to Ad agency; ");
				IaaUtil.log("add 100 to intCriteria, its targetUrl is an AdAgency");
			}
		}else{
		    connectToTarget();
		}
		//reget the image width and height
		iImgWidth = getWidth();
		iImgHeight = getHeight();
		if ( iImgWidth < IaaDebug.m_iMinImageWidth &&
				iImgHeight < IaaDebug.m_iMinImageHeight && 
				iImgWidth != AdData.UNKNOWN &&
				iImgHeight != AdData.UNKNOWN ) {
			
			//do not record this kind of small image
			return false;
		} else {
			// updated by yxy 2008-05-14
			incPossibility(getAdSizeScore(lstAdSize));
			/*if(iImgWidth==125)
			{
				IaaUtil.log("-------------------------");
				IaaUtil.log("the width of the image :" + iImgWidth);
				IaaUtil.log("the height of the image :" + iImgHeight);
				IaaUtil.log("get the intial AdSize :"+ getAdSizeScore(lstAdSize));
				IaaUtil.log("the srcURL of the image:"+ getSrcURLStr());
				IaaUtil.log("the targetURL of the image:"+ getTargetURLStr());
				IaaUtil.log("the realTargetURL of the image:"+ getRealTargetURLStr());
				IaaUtil.log("the containerURL of the image:"+ getContainerURL().getHost());
			}*/
			
			// 3. redirect ?
			if (getTargetReqStatus() == ImgLink.CONN_SUCCESS) {
				if (isPopupData()) {
					incPossibility(100);
					addReason("it is popup");
					//IaaUtil.log("add 100 to intCriteria , because it is a popupdata!");
				} else {
					try {
						String containerHost = getContainerURL().getHost();
						String targetHost = getTargetURL().getHost();
						String realHost = getRealTargetURL().getHost();
						if (!containerHost.equalsIgnoreCase(realHost)) {
							if (!containerHost.equalsIgnoreCase(targetHost)) {
								if (!targetHost.equalsIgnoreCase(realHost)) {
									// targetHost!=realHost &
									// containerHost!=targetHost &
									// containerHost!=realHost
									incPossibility(100);
									addReason("third-party redirection; ");
									//IaaUtil.log("add 100 to intCriteria , because containerHost!=targetHost!=realTargetHost!");
								} else {
									// targetHost==realHost &
									// containerHost!=targetHost &
									// containerHost!=realHost
									incPossibility(50);
									addReason("point to third-party;");
									//IaaUtil.log("add 50 to intCriteria , containerHost!=realHost, containerHost!=targetHost but realHost=targetHost");
								}
							} else {
								if (!targetHost.equalsIgnoreCase(realHost)) {
									// targetHost!=realHost &
									// containerHost==targetHost &
									// containerHost!=realHost
									incPossibility(50);
									addReason("self agency redirection;");
									//IaaUtil.log("add 50 to intCriteria , containerHost!=realHost, containerHost=targetHost,targetHost!=realHost");
								}
							}
						} else {
							if (!containerHost.equalsIgnoreCase(targetHost)) {
								// containerHost!=targetHost &
								// containerHost==realHost
								String file = getRealTargetURL().getFile();
								// IaaUtil.log("\turl : ["+
								// imgLink.realTargetUrlStr + "]");
								// IaaUtil.log("\tfile : ["+ file +"]
								// length="+file.length());

								if ((file.length() == 0)
										|| ((file.length() == 1) && file
												.equals("/"))) {
									decPossibility(75);
									addReason("thir-party redirect back to <b>HOME</b>;");
									//IaaUtil.log("decrease 75 from intCriteria , containerHost=realHost, containerHost!=targetHost,and filelength=0 or /");
								} else {
									decPossibility(25);
									addReason("third-party redirect back;");
									//IaaUtil.log("decrease 25 to intCriteria , containerHost=realHost, containerHost!=targetHost, and filelength!=0 and /");
								}
							} else {
								// containerHost==targetHost &
								// containerHost==realHost
								decPossibility(50);
								addReason("no redirection;");
								//IaaUtil.log("decrease 50 to intCriteria, containerHost=realHost=targetHost");
							}
						}

					} catch (MalformedURLException ex) {
						// !!! impossible !!!

					}
				}
			}
			return true;
		}

	}
	private boolean isAdAgency(List lstAgency)  {
		URL objHostURL = getTargetURL();
		if (objHostURL != null){
			if(lstAgency != null){
				int iCount = lstAgency.size();
				for(int iIndex = 0; iIndex < iCount; iIndex++){
					AdAgency objAgency = (AdAgency)lstAgency.get(iIndex);
					if (objAgency.IsRefering(objHostURL)){
						setAdAgency(objAgency);
						return true;
					}
				}
			}
			String urlStr = objHostURL.toString();
			if ( urlStr == null ){
				return false;
			}
			if( urlStr.toLowerCase().indexOf( "/ads/" ) !=-1 )  {
				return true;
			}
			
			if( urlStr.toLowerCase().indexOf( "/ad/" ) !=-1 )  {
				return true;
			}
		}
		return false;
	}
	//created by yxy 2008-05-14
	private int getAdSizeScore(List lstAdSize) {
		int iImgWidth = getWidth();
		int iImgHeight = getHeight();
		if(iImgWidth != 0 && iImgHeight != 0){
			if(lstAdSize != null){
				int iCount = lstAdSize.size();
				for(int iIndex = 0; iIndex <iCount; iIndex++){
					AdSize objAdSize = (AdSize)lstAdSize.get(iIndex);
					//IaaUtil.log("the objAdSize is : width:"+objAdSize.getWidth()+" height:  "+objAdSize.getHeight()+" score:  "+objAdSize.getScore());
					if(iImgWidth == objAdSize.getWidth() && iImgHeight == objAdSize.getHeight())
						return objAdSize.getScore();
				}
			}
		}
		return 25;
	}
	/* (non-Javadoc)
	 * @see com.ims.iaa.AD.AdDataLink#isConnectSuccessful()
	 */
	public boolean isConnectSuccessful() {
		if(m_iSrcReqStatus == CONN_SUCCESS){
			return true;
		}else{
			return false;
		}
	}
	
	public String toString(){
	    return "IMG: " + m_objSrcUrl.toString() + "\r\n   target: " + m_objTargetUrl;
	}
	
	//++changsheng 2006-5-16
	//when save this adlink,if this intReferenceintImpressionID is not equal 0,
	//that's indicate this ad is a drive ad
	//then will call a store procedure to copy some necessary info from the refrecence impression
	private int intReferenceintImpressionID ;
	public int getIntReferImprID()
	{
		return this.intReferenceintImpressionID ;
	}
	public void setIntReferInprID(int intReferenceintImpressionID)
	{
		this.intReferenceintImpressionID = intReferenceintImpressionID;
	}
	
	private boolean ImageConnectedFlag = false ;
	//	updated by yxy 2008-05-14
	public boolean parse1(List lstAgency, List lstAdSize) {
	    ImageConnectedFlag = true ;
		// try to figure out if this image is a ad
		int iImgWidth = getWidth();
		int iImgHeight = getHeight();
		// 1. base on the image width and height
		if ( iImgWidth < IaaDebug.m_iMinImageWidth &&
			 iImgHeight < IaaDebug.m_iMinImageHeight && 
			iImgWidth != AdData.UNKNOWN &&
			iImgHeight != AdData.UNKNOWN ) {
			
			addReason( "the image is too small; ") ;
			return false;
			
		} else {
			//			updated by yxy 2008-05-14
			//incPossibility( getAdSizeScore(lstAdSize) );
			//IaaUtil.log("the score of the Image is :"+getAdSizeScore(lstAdSize) +"the size is"+getHeight()+" * "+getWidth());
			connectToImage();
		}
		
		// 2. parse the target hostname
		if ( isAdAgency(lstAgency) ) {
			incPossibility(100);
			addReason( "point to Ad agency; ");
			//IaaUtil.log(" parse1:add 100 to intCriteria , because its targeturl is an AdAgency!");
			
		}
		
		//reget the image width and height
		iImgWidth = getWidth();
		iImgHeight = getHeight();
		if ( iImgWidth < IaaDebug.m_iMinImageWidth &&
				iImgHeight < IaaDebug.m_iMinImageHeight && 
				iImgWidth != AdData.UNKNOWN &&
				iImgHeight != AdData.UNKNOWN ) {
			//do not record this kind of small image
			return false;
		} else  {
			//			updated by yxy 2008-05-14
			incPossibility( getAdSizeScore(lstAdSize) );
			/*if(iImgWidth==125)
			{
				IaaUtil.log("=====================================");
				IaaUtil.log("the width of the image :" + iImgWidth);
				IaaUtil.log("the height of the image :" + iImgHeight);
				IaaUtil.log("get the intial AdSize :"+ getAdSizeScore(lstAdSize));
				IaaUtil.log("the srcURL of the image:"+ getSrcURLStr());
				IaaUtil.log("the targetURL of the image:"+ getTargetURLStr());
				IaaUtil.log("the realTargetURL of the image:"+ getRealTargetURLStr());
				IaaUtil.log("the containerURL of the image:"+ getContainerURL().getHost());
			}*/
			return true;	
		}
	}
	private void connectToTarget(){
	    if(getOldImpressionID() < 0){
		    HrefParser href = new HrefParser(m_objTargetUrl, m_sUserAgent);
		    if(href.connect()){
		        //++changsheng 2006-6-30 move out if(href.connect())
/*				m_objRealTargetUrl = href.getRedirectURL();
				m_sAdvertiser = m_objRealTargetUrl.getHost();*/
				m_iTargetReqStatus = CONN_SUCCESS;
		    }else{
		        m_iTargetReqStatus = CONN_FAILURE;
		    }				
		    m_objRealTargetUrl = href.getRedirectURL();
			m_sAdvertiser = m_objRealTargetUrl.getHost();
		}
	}
	private void connectToImage(){
		// try to get the image source content.
		URLConnection uc = null;
		m_objCookie = new SimpleCookies();

		try  {
		    HrefParser href = new HrefParser(m_objSrcUrl, m_sUserAgent);
		    if(!href.connect()){
		        //even it is fail, we still need get the mime type.
				m_objImage.setDataType(href.getMimeType());
				m_iSrcReqStatus = CONN_FAILURE;
		        return;
		    }
		    //get the redirect URL
		    m_objSrcUrl=href.getRedirectURL();
			
		    uc = href.getConnection();
			//read cookie after connect()
			m_objCookie.readCookies( uc );
			m_objImage.setDataType(href.getMimeType());
			m_objImage.setDataSize(href.getContentLength());
			m_sImageSite = uc.getURL().getHost();
			m_iSrcReqStatus = CONN_SUCCESS;
		} catch(Exception e)  {
			if(IaaDebug.Debug) 			
				IaaUtil.log("!!!!Error make connection to the image " + e);		
		}

		m_objCollectTime = new Timestamp(  System.currentTimeMillis() );
		if (AdImage.SAVEIMAGE && (m_objImage.getDataSize() < AdImage.MAXIMAGESIZE))  {
			if(IaaDebug.AuxDebug)IaaDebug.begin("connect to the image ");		
			try  {
				IaaDebug.begin("getInputStream for image" + uc.getURL());
				BufferedInputStream bs = new BufferedInputStream(uc.getInputStream());
				IaaDebug.end("getInputStream " + uc.getURL());
	
				byte[] buf = new byte[5120];
				int readNum =0;

				ByteArrayOutputStream picOutStream = new ByteArrayOutputStream();

				IaaDebug.begin("read image inputStream " + uc.getURL());
				while ( (readNum = bs.read(buf)) != -1)  {
						picOutStream.write(buf,0,readNum);
				}
				
				bs.close();
				IaaDebug.end("read image inputStream " + uc.getURL());
				if(m_objImage.getDataSize() == AdImage.MAXIMAGESIZE-1)
				{
					IaaUtil.log("connectToImage-->the size of the image now is  " + m_objImage.getDataSize() );
					m_objImage.setDataSize(picOutStream.toByteArray().length);//added by yxy 2008-7-4
					IaaUtil.log("connectToImage-->the size of the image after updated is "+m_objImage.getDataSize());
				}
				m_objImage.setData(picOutStream.toByteArray());
				
				IaaDebug.end("set image data");
				
				// picOutStream.size() should equals to the length of imageData array
				// imageSize = picOutStream.size();
				picOutStream.close();
				if(IaaDebug.AuxDebug)IaaDebug.end("connect to the image ");
			} catch ( Exception e ) {
				m_iSrcReqStatus = CONN_FAILURE;
				IaaUtil.log( "Get image from the connection input stream error " + e );
			}
		} else {
			if(IaaDebug.Debug) IaaUtil.log("Image data too big to be saved.");	
			//Note: either image is too big or we do not want to save the image, 
			// then the imageData is still null
			// imageSize = imageData.length;
		}
		
		m_objImage.prepareImageHeight();
		IaaDebug.end("get image height");
		m_objImage.prepareImageWidth();
		IaaDebug.end("get image width");
		//after save the image data and get the widht and height,
		//if can't get the width and height, set it to web page setting
		if(m_objImage.getWidth() == AdData.NOTEXIST || m_objImage.getHeight() == AdData.NOTEXIST){
		    m_objImage.setHeight(m_iHeight);
		    m_objImage.setWidth(m_iWidth);
		}
	}
}

